Introduce Test
品質要求
設計品質(Scalable)
概念完整
可維護性
可重用性
系統品質
可測試性
可支持性
運行品質(HA)
可用性,互操作性,可管理性,
性能,可靠性,可擴展性,安全性
使用品質
易用性
V-Model
Type of Software testing
BDD metamodel
Cucumber
Double Loop Workflow
Requirement
Overview
Impact Mapping
User Story
Feature Scenario
Goal
Deliverable
Impact
Actor
Impact
Actor
Deliverable
Deliverable
Cucumber
User Story Template:
As a < role,who >, I
want to
<do something,what
> so that I can
<achieve some
benifit ,why>.
Usecase to Sprint
Level of Requirement
Vision
Scope
Roadmap
Theme
Business Value
Priority
Use Case
Customer Requirment
Logical grouping of use case
Function
Feature
User need based scenario
Acceptance criteria
Task
User Story
Them
Hight-Level Details(Product)
Mid-Level (Release)
Low-Level Detail (Sprint)
Scope of REQ
Usecase Use
case
UseCase TO Tasks
Requirement SPEC
Detail Just in Time
User Story vs Use Case
User Stories Use Cases
As a <
role >, I want to
<do
something> so that I
can <
achieve some
benifit
>.
#Title:
"goal the use case is trying to satisfy"
#Main Success Scenario
:numbered list of
steps
+Step: "a simple statement of the
interaction between the actor and a system"
#Extensions:
separately numbered lists, one
per Extension
+Extension: "a condition that results in
different interactions from .. the main success
scenario". An extension from main step 3 is
numbered 3a, etc.
Use Cases vs User Stories
The Similarity
If we consider the key component in both approaches:
Use Cases contain equivalent elements: an actor, flow of
events and post conditions respectively (a detailed Use
Case template may contain many more other elements).
User Stories contain, with user role, goal and
acceptance criteria.
Use Cases vs User Stories
The Difference
The details of a User Story may not be documented to the
same extreme as a Use Case.
User Stories deliberately leave out a lot of important
details. User Stories are meant to elicit conversations by
asking questions during scrum meetings.
Small increments for getting feedback more frequently,
rather than having more detailed up-front requirement
specification as in Use Cases.
Specification by example (SBE)
Requirement Description
Feature User Story Scenario
Serve coffee
In order to earn
money Customers
should be able to buy
coffee at all times
Scenario:
Buy last coffee
Given
there are 1 coffees left in the
machine
And I have deposited 1 dollar
When I press the coffee button
Then I should be served a coffee
Template:
As a < role
>, I want to
<do
something
> so that
I can <
achieve some
benifit
>.
Template:
A simple statement of the interaction
between the actor and a system
Specification by Example
Feature: 訂單結案時獲得紅利點數 # Title
身為一名銷售主管 # Description
我想要讓顧客在訂單結案後獲得點數
這樣就能提供誘因繼續再我們的商城消費
Scenario: 普通等級客可以獲得 10
Given 我是有一名普通等級客
And 我有一筆待結案訂單
When 我的訂單結案時
Then 我應該獲得 10 點紅利點數
Scenario: VIP 等級客可以獲得 20
Given 我是有一名 VIP 等級客
And 我有一筆待結案訂單
When 我的訂單結案時
Then 我應該獲得 20 點紅利點數
...
BDD metamodel
User Story Mapping
Service blueprint
Service blueprint
MVP vs MMF vs Product Backlog
Backlog to MVP
Test Double
Collaborators(DOC)
A collaborator is some
function, data, module,
or device outside the
code under test (CUT)
that the CUT depends
upon.
DOC : Depended on
Components
Dependency mess
Test dependency tree
SUT : System Under Test
CUT : Code Under Test
DOC : Depended on
Components
Breaking Dependencies
Input and Output
Test Doubles Variations
Name
Variation
Test dummy
Keeps the linker from rejecting your build. A dummy is a simple stub that is never called. It is provided to
satisfy the complier, linker, or runtime dependency.
Test stub
Returns some
value, as directed by the current test case.
Test spy
Captures the parameters passed from the CUT so the test can verify that the correct parameters have been
passed to the CUT. The spy can also feed return
values to the CUT just like a test stub.
Mock object
Verifies
the functions called, the call order and
the parameters passed from the CUT to the DOC. It also is
programmed to return specific
values to the CUT. The mock object is usually dealing with a situation
where multiple calls are made to it, and each call and response are potentially different.
Fake object
Provides a partial implementation for the replaced component. The fake usually has a simplified
implementation when
compared to the replaced implementation.
Exploding fake
Causes the test to fail if it is called.
Mock maintenance costs are quite high. In practice, Stub: Mock is about 90%: 10%. Stub is used in most
cases.
Spectrum of Test Doubles
When to Use aT est Double
Hardware independence
Inject difficult to produce input(s)
Speed up a slow collaborator
Dependency on something unstable
Dependency on something under development
Dependency on something that is difficult to configure
Test Stub
We replace a real
object with a test-
specific object
that feeds the
desired indirect
inputs into the
SUT.
Test Stub
DOC
Test Spy
Use a Test Double to
capture the indirect
output calls made to
another component
by the SUT for later
verification by the
test.
Mock Object
Replace an
object the SUT
depends on with
a test-specific
object that
verifies it is
being used
correctly by the
SUT.
Mock Object
Fake
Replace a
component that the
system under test
(SUT) depends on
with a much lighter-
weight
implementation.
Fake
Flash driver and its test fixture
Substitutions in C
8.3 Link-Time Substitution with Object file
9.2 Function Pointer Substitution
Preprocessor Substitution
Link-Time & Function Pointer Substitution
Object Oriented C
Encapsulation
Encapsulation
Declaration of the Shape “class” in C (shape.h header file)
#ifndef SHAPE_H
#define SHAPE_H
/* Shape's attributes... */
typedef struct {
int16_t x; /* x-coordinate of Shape's position */
int16_t y; /* y-coordinate of Shape's position */
} Shape;
/* Shape's operations (Shape's interface)... */
void Shape_ctor(Shape * const me, int16_t x, int16_t y);
void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy);
int16_t Shape_getX(Shape * const me);
int16_t Shape_getY(Shape * const me);
#endif /* SHAPE_H */
UML Class Diagram of the Shape class
Encapsulation
Definition of the Shape “class” in C (file shape.c)
#include "shape.h" /* Shape class interface */
/* constructor implementation */
void Shape_ctor(Shape * const me, int16_t x, int16_t y) {
me->x = x;
me->y = y;
}
/* move-by operation implementation */
void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy) {
me->x += dx;
me->y += dy;
}
/* "getter" operations implementation */
int16_t Shape_getX(Shape * const me) {
return me->x;
}
int16_t Shape_getY(Shape * const me) {
return me->y;
}
NOTE: The “me” pointer in C
corresponds directly to the
implicit “this” pointer in C++.
Encapsulation
Examples of using the Shape class in C (file main.c)
#include "shape.h" /* Shape class interface */
#include <stdio.h> /* for printf() */
int main() {
Shape s1, s2; /* multiple instances of Shape */
Shape_ctor(&s1, 0, 1);
Shape_ctor(&s2, -1, 2);
printf("Shape s1(x=%d,y=%d)\n", Shape_getX(&s1), Shape_getY(&s1));
printf("Shape s2(x=%d,y=%d)\n", Shape_getX(&s2), Shape_getY(&s2));
Shape_moveBy(&s1, 2, -4);
Shape_moveBy(&s2, 1, -2);
printf("Shape s1(x=%d,y=%d)\n", Shape_getX(&s1), Shape_getY(&s1));
printf("Shape s2(x=%d,y=%d)\n", Shape_getX(&s2), Shape_getY(&s2));
return 0;
}
Inheritance
Inheritance
Declaration of the Rectangle as a Subclass of Shape (file rect.h)
#ifndef RECT_H
#define RECT_H
#include "shape.h" /* the base class interface */
/* Rectangle's attributes... */
typedef struct {
Shape super; /* <== inherits Shape */
/* attributes added by this subclass... */
uint16_t width;
uint16_t height;
} Rectangle;
/* constructor prototype */
void Rectangle_ctor(Rectangle * const me, int16_t x, int16_t
y,
uint16_t width, uint16_t height);
#endif /* RECT_H */
class diagram with inheritance
Inheritance
Single inheritance in C:
(a) class diagram with
inheritance, and
(b) memory layout for
Rectangle and Shape
objects
Inheritance
The Constructor of class Rectangle (file rect.c)
#include "rect.h"
/* constructor implementation */
void Rectangle_ctor(Rectangle * const me, int16_t x, int16_t y,uint16_t width,
uint16_t height)
{
/* first call superclassctor */
Shape_ctor(&me->super, x, y);
/* next, you initialize the attributes added by this subclass... */
me->width = width;
me->height = height;
}
Inheritance
Example of Using Rectangle Objects (file main.c)
#include "rect.h" /* Rectangle class interface */
#include <stdio.h> /* for printf() */
int main() {
Rectangle r1, r2; /* multiple instances of Rect */
/* instantiate rectangles... */
Rectangle_ctor(&r1, 0, 2, 10, 15);
Rectangle_ctor(&r2, -1, 3, 5, 8);
printf("Rect r1(x=%d,y=%d,width=%d,height=%d)\n",
r1.super.x, r1.super.y, r1.width, r1.height);
/* re-use inherited function from the superclass Shape... */
Shape_moveBy((Shape *)&r1, -2, 3);
Shape_moveBy(&r2.super, 2, -1);
printf("Rect r1(x=%d,y=%d,width=%d,height=%d)\n",
r1.super.x, r1.super.y, r1.width, r1.height);
return 0;
}
(Virtual Functions)
Polymorphism
Polymorphism
Declaration of the Shape base class (file shape.h)
#ifndef SHAPE_H
#define SHAPE_H
#include <stdint.h>
/* Shape's attributes... */
struct ShapeVtbl; /* forward declaration */
typedef struct {
(1) struct ShapeVtbl const *vptr; /* <== Shape's Virtual Pointer */
int16_t x; /* x-coordinate of Shape's position */
int16_t y; /* y-coordinate of Shape's position */
} Shape;
/* Shape's virtual table */
(2) struct ShapeVtbl {
(3) uint32_t (*area)(Shape const * const me);
(4) void (*draw)(Shape const * const me);
};
Polymorphism
Declaration of the Shape base class (file shape.h)
/* Shape's operations (Shape's interface)... */
void Shape_ctor(Shape * const me, int16_t x, int16_t y);
void Shape_moveBy(Shape * const me, int16_t dx, int16_t dy);
static inline uint32_t Shape_area(Shape const * const me) {
(5) return (*me->vptr->area)(me);
}
static inline void Shape_draw(Shape const * const me) {
(6) (*me->vptr->draw)(me);
}
/* generic operations on collections of Shapes */
(7) Shape const *largestShape(Shape const *shapes[], uint32_t nShapes);
(8) void drawAllShapes(Shape const *shapes[], uint32_t nShapes);
#endif /* SHAPE_H */
Polymorphism
Design Principles
TOPICS
SOLID
DRY
KISS
YAGNI
SOLID
Single Responsibility Principle
Open Closed Principle
Liskov Substitution Principle
Interface Segregation Principle
Dependency Inversion Principle
Single Responsibility Principle
Each class in your
system should have
only one
responsibility
There should never
be more than one
reason for a class to
change.
Focused on
Responsibility of class
Open Closed Principle
Software entities
like classes,
modules and
functions should be
open for extension
but closed for
modifications.
Open Closed Principle
Dependency
Implements
Open Closed Principle
Inheritance Polymorphism
Implements
extends
Open
Open
Closed Closed
open for extension, but closed for modification
dependency
Horizontal Framework
(Microsoft Foundation Classes)
dependency
Liskov Substitution Principle
Subtypes must be substitutable for their base types
If Sis a subtype of T,
then objects of type T
may be replaced with
objects of type S
without altering any of
the desirable
properties of the
program (correctness,
task performed, etc.)
<T>
<S>
Focused on Implemented Class
Interface Segregation Principle
Focused on Client Functions
The interface-
segregation
principle states that
no client should be
forced to depend on
methods it does not
use.
Dependency Inversion Principle
program to an interface, not an implementation
High-level modules
should not depend
on low-level
modules. Both
should depend on
abstractions.
Abstractions should
not depend on
details. Details
should depend on
abstractions.
Dependency Injection(DI)
Non DI DI using Constructor
class Programmer {
Computer computer;
Programmer() {
computer = new Computer();//non
di
}
void code(){
computer.program();
}
}
class Programmer {
Computer computer;
Programmer(Computer c) {
computer = c;//is the DI
}
void code(){
computer.program();
}
}
Inversion of Control(IoC)
class Work { // like a IoC container
public static void main(String[] args) {
Computer computer = new Computer();
Programmer programmer = new
Programmer(computer);
}
}
Decoupling programer and computer using IoC container like work.
Dependency Inversion Principle
interface Programmable {
void program();
}
class Computer implements
Programmable {
@Override
void program(){
//computer program
}
}
class Programmer {
Programmable programmable;
Programmer(Programmable p) {
programmable = p;
}
void code(){
programmable.program();
}
}
Dependency
implements
DIP , DI , IoC
Applications of DIP
DRY - Don’t Repeat Yourself
KISS - Keep it simple, stupid!
YAGNI - You aren't gonna need it
(Need)